﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SomeGame.GUI.Screens;
using SomeGame.GUI.Widgets.Containers;

namespace SomeGame.GUI.Widgets {

    public abstract class Widget {

        public int? Bottom;
        public Color CurrentColor;
        public Display Display;
        public HorizontalAlignment HorizontalAlignment = HorizontalAlignment.Left;
        public Color? HoverColor;
        public string ID;
        public int? Left;
        public Margin Margin;
        public Color NormalColor;
        public Padding Padding;
        public Widget Parent;
        public Position Position;
        public int? Right;
        public Screen Screen;
        protected Texture2D Texture;
        public int? Top;
        private Rectangle bounds;
        public int? height;
        private int? width;

        protected Widget() : this(null, 0, 0, Color.White) {
            // ...
        }

        protected Widget(Texture2D texture,
            Color color,
            Display display = Display.Inline,
            Position position = Position.Relative)
            : this(texture, texture.Width, texture.Height, color, display, position) {
            // ...
        }

        protected Widget(Texture2D texture,
            int width,
            int height,
            Color color,
            Display display = Display.Inline,
            Position position = Position.Relative) {
            Texture = texture;
            Height = height;
            Width = width;
            NormalColor = color;
            CurrentColor = NormalColor;
            Display = display;
            Position = position;
        }

        public int? Width {
            get { return width; }
            set {
                width = value;
                if (value != null && value != Bounds.Width) {
                    bounds.Width = width.Value;
                }
            }
        }
        public int? Height {
            get { return height; }
            set {
                height = value;
                if (value != null && value != Bounds.Height) {
                    bounds.Height = height.Value;
                }
            }
        }
        public Rectangle Bounds {
            get { return bounds; }
            set {
                // If this is a container, move it's children by the amount this has moved.
                // This will reactively cascade down through the layout.
                var container = this as Container;
                if (container != null) {
                    int xDelta = value.X-Bounds.X;
                    int yDelta = value.Y-Bounds.Y;
                    foreach (Widget child in container.Children) {
                        Rectangle temp = child.Bounds;
                        temp.X += xDelta;
                        temp.Y += yDelta;
                        child.Bounds = temp;
                    }
                }
                bounds = value;
                Width = value.Width;
                Height = value.Height;
            }
        }

        public virtual void Update(GameTime gameTime) {
            // Doing nothing is the baseline functionality.
        }

        public virtual void Draw() {
            if (CurrentColor == Color.Transparent || Display == Display.None) {
                return;
            }
            GameEngine.SpriteBatch.Draw(Texture, bounds, CurrentColor);
        }

    }

    public enum Display {

        Inline,
        Block,
        None

    }

    public enum Position {

        Relative,
        Absolute

    }

    public enum HorizontalAlignment {

        Left,
        Center,
        Right

    }

    public struct Margin {

        public int Bottom;
        public int Left;
        public int Right;
        public int Top;

        public Margin(int top, int right, int bottom, int left) {
            Top = top;
            Right = right;
            Bottom = bottom;
            Left = left;
        }

        public Margin(int topAndBottom, int leftAndRight) : this(topAndBottom, leftAndRight, topAndBottom, leftAndRight) {
            // ...
        }

        public Margin(int allSides) : this(allSides, allSides, allSides, allSides) {
            // ...
        }

    }

    public struct Padding {

        public int Bottom;
        public int Left;
        public int Right;
        public int Top;

        public Padding(int top, int right, int bottom, int left) {
            Top = top;
            Right = right;
            Bottom = bottom;
            Left = left;
        }

        public Padding(int topAndBottom, int leftAndRight)
            : this(topAndBottom, leftAndRight, topAndBottom, leftAndRight) {
            // ...
        }

        public Padding(int allSides) : this(allSides, allSides, allSides, allSides) {
            // ...
        }

    }

}